home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / presto / prest_04.lha / src / presto.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-08  |  5.2 KB  |  220 lines

  1. /*
  2.  * presto.c
  3.  *
  4.  *    Main PRESTO bootstrapping code.  Works something like this:
  5.  *
  6.  *    main()
  7.  *        Create a new MAIN object.
  8.  *        delete the scheduler thread
  9.  *        exit
  10.  *
  11.  *    Main::Main()
  12.  *        Call Main::init giving programmer chance to set up
  13.  *        initial parameters.
  14.  *
  15.  *    -    Bind "thisthread" to the default thread we get from UNIX.
  16.  *    -    Create a new scheduler object.
  17.  *    -    Create a thread to run in the scheduler object.
  18.  *    -    Start new thread in scheduler object.  We are running 
  19.  *        without preemption and with a single processor at this
  20.  *        point, so the start just puts the thread/scheduler pair
  21.  *        on the ready queue.
  22.  *    -    Create nummainthreads bound to Main::main and "start" them
  23.  *        by placing them on the run queue.  Again, we know that 
  24.  *        they won't run until the scheduler actually kicks in.
  25.  *
  26.  *    -    Invoke "thisproc" getting it to start pulling threads
  27.  *        off the readyq.
  28.  */
  29.  
  30. #define _PRESTO_C
  31.  
  32.  
  33. #include <sys/types.h>
  34. #include <osfcn.h>
  35. #include <stream.h>
  36. #include "presto.h"
  37.  
  38. Scheduler    *sched;            // does not need to be shared,
  39.                     // just what it references does
  40.  
  41. static int main_exit_code = 0;        // how we leave
  42. shared_t int prestoState = STATIC_CTOR;
  43.  
  44. Main::Main(int ac, char **ap, char **ep)
  45. {
  46.     int strlen(char*);
  47.     int strcpy(char*, char*);
  48.     Thread *t, *mainthread;
  49.  
  50.     argc = ac;
  51.     argv = ap;
  52.     envp = ep;
  53.     numprocessors = 1;
  54.     mainstacksizes = DEFSTACKSIZ;
  55.     nummainthreads = 1;
  56.     quantum = DEFQUANTUM;
  57.  
  58.     mainthread = new Thread("_MAIN_", 0, 0);    // run on same stack
  59.     mainthread->setflags(TF_SCHEDULER|TF_KEEPSTACK|TF_NONPREEMPTABLE);
  60.  
  61.     //
  62.     // "thisthread" refers to the current thread of execution running
  63.     // right here, right now.  Make our thread point at the static process
  64.     // object until we have our own process object to reference into.
  65.     //
  66.     mainthread->setproc(sysproc);
  67.     thisthread = mainthread;
  68.  
  69.     prestoState = MAIN_INIT;
  70.     // give the programmer a chance
  71.     if (main_exit_code = Main::init())    {    // non-zero return
  72.         return;                    // is bad news
  73.     }
  74.  
  75. #ifdef sun
  76.     numprocessors = 1;
  77. #endif sun
  78. #ifdef vax
  79.     // VAX unix version runs on uniprocessors only for now.
  80.     numprocessors = 1;
  81. #endif vax
  82.  
  83.     if (thisthread != mainthread)
  84.         thisthread = mainthread;
  85.     prestoState = MAIN_MAIN;
  86.  
  87.     //
  88.     // prime the scheduler
  89.     //
  90.     if (sched == (Scheduler*)0)
  91.         sched = new Scheduler(numprocessors,quantum);    // sets thisproc
  92.  
  93.     //
  94.     // t becomes the first schedulable thread
  95.     // Since we only have one processor, and no preemption here
  96.     // we return with t on the ready q.
  97.     //
  98.     t = mainthread->newthread("SCHEDULER_STARTER");
  99.     t->nonpreemptable();
  100.  
  101.     t->start(sched, (PFany)(sched->invoke));    
  102.  
  103.     //
  104.     // Build the main threads and readyq them
  105.     //
  106.     for (int i = 0; i < nummainthreads; i++)    {
  107.         char buf[8];        // lotsa threads
  108.         sprintf(buf,"%s.%d", MAINNAME, i);
  109.         char *name = new char[strlen(buf)+1];
  110.         strcpy(name, buf);
  111.         Thread *t = mainthread->newthread(name, i+1, mainstacksizes);
  112.         t->start(this, (PFany)(this->main));
  113.     }
  114.  
  115.     // Crank up the scheduler in the context of thisthread.
  116.     //    This will read the SCHEDULER thread off the
  117.     //    the readyq, invoke that thread
  118.     //    on the scheduler itself, which will cause the scheduler
  119.     //    to then create numprocessors copies of itself (each
  120.     //    running on its own stack).  The SCHEDULER thread
  121.     //    is guaranteed not to block and will be the first thread
  122.     //    to terminate, so we can quickly reuse it.
  123.     //    
  124.  
  125.     //
  126.     // Bind this thread to a processor which will start up all the
  127.     // coschedulers.  Thisthread will not be queued since it's a scheduler.
  128.     // We have to start it up directly.
  129.     //
  130.  
  131.     mainthread->isrunning();
  132.     thisproc->invoke();        // start thisproc which will start 
  133.                     // the scheduler thread which will
  134.                     // start all the processor threads
  135.                     // which will then pull the main
  136.                     // threads off the readyq
  137.     mainthread->isnotrunning();
  138.  
  139.     //
  140.     // Since shutdown is not synchronized, there is a race condition which
  141.     // can result in sched getting deleted while process objects are still
  142.     // active.  If it hurts, don't do it.
  143.     //
  144.     //    if (sched)
  145.     //        delete sched;
  146.     //
  147.  
  148.     delete thisproc;
  149.     thisproc = sysproc;
  150.  
  151.     //delete thisthread;         /* done in runrun */
  152.     //thisthread = 0;
  153.     //
  154.     // Threads are out... thisthread is undefined at this point
  155.     //
  156.     cout << "HALT\n";        // should be single unix process
  157.     prestoState = MAIN_DONE;
  158.     main_exit_code = Main::done();
  159. }
  160.  
  161.  
  162. Main::~Main()
  163. {
  164. }
  165.  
  166.  
  167. //
  168. // Preallocate tons of threads in the parent process's address space.
  169. // This is a temporary hack to get around the brain-damaged sequent
  170. // shared memory implementation.
  171. //
  172. // NOTE: not called from anywhere in Presto.
  173. //
  174. int
  175. Main::preallocthreads(int cnt, int sz)
  176. {
  177.     int j;
  178.  
  179.     j = cnt;
  180.     Thread **tlist = new Thread*[j];
  181.     while (j--)    {    
  182.         tlist[j] = thisthread->newthread("any",    
  183.                     0,    // any id
  184.                     sz,    // stack size
  185.                     1);    // must have stack
  186.     }
  187.     j = cnt;
  188.     while (j--)    {
  189.         delete tlist[j];
  190.     }
  191.     delete tlist;
  192.     return cnt;
  193. }
  194.  
  195. typedef void    (*PF)();
  196. extern PF set_new_handler(PF);
  197. extern void failed_malloc();
  198.  
  199. void
  200. main(int argc, char **argv, char **envp)
  201. {
  202.     set_new_handler(failed_malloc);
  203.  
  204.     //
  205.     // Create a new main thread
  206.     //
  207.     Main    *MAIN = new Main(argc, argv, envp);
  208.  
  209.     if (MAIN)
  210.         delete MAIN;
  211.  
  212.     prestoState = STATIC_DTOR;
  213.  
  214.     extern wait(int*);
  215.     while (::wait(0) != -1)        // collect kids, get execution stats
  216.         continue;
  217.  
  218.     exit(main_exit_code);
  219. }    
  220.